/**
 * 接口调用中间层
 * 基于uni.request封装，提供统一的API调用接口
 * 支持请求/响应拦截器、错误处理、loading管理等功能
 * 支持Mock数据模拟
 */

import mockHandler from '../mock/index'
import sqliteApi from '../sqlite/sqlite'
import config from '../config/index'

// 默认配置
const DEFAULT_CONFIG = {
  baseURL: config.api.baseURL,
  timeout: 10000,
  header: {
    'Content-Type': 'application/json'
  },
  showLoading: true,
  loadingText: '加载中...',
  showError: true,
  useMock: config.api.useMock || false, // 是否使用Mock数据
  dataSource: config.api.dataSource || 'remote' // 数据源类型
}

// 请求状态码映射
const STATUS_CODE = {
  SUCCESS: 200,
  UNAUTHORIZED: 401,
  FORBIDDEN: 403,
  NOT_FOUND: 404,
  SERVER_ERROR: 500,
  NETWORK_ERROR: -1
}

// 错误消息映射
const ERROR_MESSAGES = {
  [STATUS_CODE.UNAUTHORIZED]: '登录已过期，请重新登录',
  [STATUS_CODE.FORBIDDEN]: '没有权限访问',
  [STATUS_CODE.NOT_FOUND]: '请求的资源不存在',
  [STATUS_CODE.SERVER_ERROR]: '服务器内部错误',
  [STATUS_CODE.NETWORK_ERROR]: '网络连接失败，请检查网络设置',
  'timeout': '请求超时，请稍后重试',
  'default': '请求失败，请稍后重试'
}

class RequestManager {
  constructor() {
    this.config = { ...DEFAULT_CONFIG }
    this.requestInterceptors = []
    this.responseInterceptors = []
    this.loadingCount = 0
  }

  /**
   * 设置全局配置
   * @param {Object} config 配置对象
   */
  setConfig(config) {
    this.config = { ...this.config, ...config }
  }

  /**
   * 添加请求拦截器
   * @param {Function} fulfilled 成功回调
   * @param {Function} rejected 失败回调
   */
  addRequestInterceptor(fulfilled, rejected) {
    this.requestInterceptors.push({ fulfilled, rejected })
  }

  /**
   * 添加响应拦截器
   * @param {Function} fulfilled 成功回调
   * @param {Function} rejected 失败回调
   */
  addResponseInterceptor(fulfilled, rejected) {
    this.responseInterceptors.push({ fulfilled, rejected })
  }

  /**
   * 显示loading
   * @param {String} title loading文本
   */
  showLoading(title = '加载中...') {
    if (this.loadingCount === 0) {
      uni.showLoading({
        title,
        mask: true
      })
    }
    this.loadingCount++
  }

  /**
   * 隐藏loading
   */
  hideLoading() {
    this.loadingCount--
    if (this.loadingCount <= 0) {
      this.loadingCount = 0
      uni.hideLoading()
    }
  }

  /**
   * 显示错误提示
   * @param {String} message 错误消息
   */
  showError(message) {
    uni.showToast({
      title: message,
      icon: 'none',
      duration: 2000
    })
  }

  /**
   * 处理请求拦截器
   * @param {Object} config 请求配置
   * @returns {Object} 处理后的配置
   */
  async processRequestInterceptors(config) {
    let processedConfig = config
    
    for (const interceptor of this.requestInterceptors) {
      try {
        if (interceptor.fulfilled) {
          processedConfig = await interceptor.fulfilled(processedConfig)
        }
      } catch (error) {
        if (interceptor.rejected) {
          return interceptor.rejected(error)
        }
        throw error
      }
    }
    
    return processedConfig
  }

  /**
   * 处理响应拦截器
   * @param {Object} response 响应对象
   * @returns {Object} 处理后的响应
   */
  async processResponseInterceptors(response) {
    let processedResponse = response
    
    for (const interceptor of this.responseInterceptors) {
      try {
        if (interceptor.fulfilled) {
          processedResponse = await interceptor.fulfilled(processedResponse)
        }
      } catch (error) {
        if (interceptor.rejected) {
          return interceptor.rejected(error)
        }
        throw error
      }
    }
    
    return processedResponse
  }

  /**
   * 获取错误消息
   * @param {Number|String} code 错误码
   * @returns {String} 错误消息
   */
  getErrorMessage(code) {
    return ERROR_MESSAGES[code] || ERROR_MESSAGES.default
  }

  /**
   * 处理SQLite请求
   * @param {Object} config 请求配置
   * @returns {Promise} SQLite响应
   */
  async handleSqliteRequest(config) {
    try {
      // 显示loading
      if (config.showLoading) {
        this.showLoading(config.loadingText)
      }

      // 解析请求路径和方法
      let path = config.url.replace(config.baseURL, '')
      
      // 移除开头的斜杠
      if (path.startsWith('/')) {
        path = path.substring(1)
      }
      
      // 移除查询参数（如时间戳）
      if (path.includes('?')) {
        path = path.split('?')[0]
      }
      const method = config.method.toUpperCase()
      const data = config.data || {}
      
      // 路由到对应的SQLite API
      let result
      const pathSegments = path.split('/').filter(Boolean)
      const module = pathSegments[0] // 模块名：users, habits, finance等
      const id = pathSegments[1] // 资源ID（如果有）
      const action = pathSegments[2] // 操作名：complete, activate等特殊操作
      
      
      if (sqliteApi[module]) {
        // 根据HTTP方法和路径确定调用的API方法
        if (method === 'GET') {
          if (id && action) {
            // GET /module/id/action - 特定资源的特定操作（如获取习惯历史记录）
            const methodName = action.replace(/-([a-z])/g, (g) => g[1].toUpperCase())
            if (sqliteApi[module][methodName]) {
              result = await sqliteApi[module][methodName](id, data)
            } else {
              throw new Error(`SQLite API method ${methodName} not found`)
            }
          } else if (id) {
            // GET /module/id - 获取单个资源
            const methodName = `get${module.charAt(0).toUpperCase() + module.slice(1, -1)}Detail`
            if (sqliteApi[module][methodName]) {
              result = await sqliteApi[module][methodName](id)
            } else {
              throw new Error(`SQLite API method ${methodName} not found`)
            }
          } else {
            // GET /module - 获取列表
            const methodName = `get${module.charAt(0).toUpperCase() + module.slice(1)}List`
            if (sqliteApi[module][methodName]) {
              result = await sqliteApi[module][methodName](data)
            } else {
              throw new Error(`SQLite API method ${methodName} not found`)
            }
          }
        } else if (method === 'POST') {
          if (id && action) {
            // POST /module/id/action - 特定资源的特定操作（如完成习惯、激活用户）
            const methodName = action.replace(/-([a-z])/g, (g) => g[1].toUpperCase())
            if (sqliteApi[module][methodName]) {
              result = await sqliteApi[module][methodName](id, data)
            } else {
              throw new Error(`SQLite API method ${methodName} not found`)
            }
          } else if (!id && !action) {
            // POST /module - 创建资源
            const methodName = `create${module.charAt(0).toUpperCase() + module.slice(1, -1)}`
            if (sqliteApi[module][methodName]) {
              result = await sqliteApi[module][methodName](data)
            } else {
              throw new Error(`SQLite API method ${methodName} not found`)
            }
          } else {
            throw new Error('Invalid POST request path structure')
          }
        } else if (method === 'PUT') {
          if (id && !action) {
            // PUT /module/id - 更新资源
            const methodName = `update${module.charAt(0).toUpperCase() + module.slice(1, -1)}`
            if (sqliteApi[module][methodName]) {
              result = await sqliteApi[module][methodName](id, data)
            } else {
              throw new Error(`SQLite API method ${methodName} not found`)
            }
          } else {
            throw new Error('PUT request requires resource ID and no action')
          }
        } else if (method === 'DELETE') {
          if (id && action) {
            // DELETE /module/id/action - 特定资源的特定删除操作（如取消完成习惯）
            const methodName = action.replace(/-([a-z])/g, (g) => g[1].toUpperCase())
            if (sqliteApi[module][methodName]) {
              result = await sqliteApi[module][methodName](id, data)
            } else {
              throw new Error(`SQLite API method ${methodName} not found`)
            }
          } else if (id && !action) {
            // DELETE /module/id - 删除资源
            const methodName = `delete${module.charAt(0).toUpperCase() + module.slice(1, -1)}`
            if (sqliteApi[module][methodName]) {
              result = await sqliteApi[module][methodName](id)
            } else {
              throw new Error(`SQLite API method ${methodName} not found`)
            }
          } else {
            throw new Error('DELETE request requires resource ID')
          }
        } else {
          throw new Error(`Unsupported HTTP method: ${method}`)
        }
      } else {
        throw new Error(`SQLite API module '${module}' not found`)
      }

      // 隐藏loading
      if (config.showLoading) {
        this.hideLoading()
      }

      // 构造响应对象
      const response = {
        data: {
          code: 200,
          message: 'success',
          data: result
        },
        statusCode: 200,
        header: {
          'content-type': 'application/json'
        },
        config
      }

      // 处理响应拦截器
      return await this.processResponseInterceptors(response)
      
    } catch (error) {
      // 隐藏loading
      if (config.showLoading) {
        this.hideLoading()
      }

      // 处理SQLite错误
      const sqliteError = {
        message: error.message || 'SQLite请求失败',
        code: 500,
        response: {
          data: {
            code: 500,
            message: error.message || 'SQLite请求失败'
          },
          statusCode: 500,
          header: {
            'content-type': 'application/json'
          }
        },
        config
      }

      if (config.showError) {
        this.showError(sqliteError.message)
      }

      throw sqliteError
    }
  }

  /**
   * 处理Mock请求
   * @param {Object} config 请求配置
   * @returns {Promise} Mock响应
   */
  async handleMockRequest(config) {
    try {
      // 显示loading
      if (config.showLoading) {
        this.showLoading(config.loadingText)
      }

      // 构造Mock请求路径
      const mockPath = config.url.replace(config.baseURL, '')
      const mockKey = `${config.method.toUpperCase()} ${mockPath}`
      
      // 调用Mock处理器
      const mockResponse = await mockHandler.mockRequest(mockPath, config.method, config.data)
      
      // 如果Mock处理器返回null，说明没有对应的Mock数据
      if (mockResponse === null) {
        throw new Error(JSON.stringify({
          code: 404,
          message: `Mock数据未找到: ${mockKey}`
        }))
      }
      
      const mockData = mockResponse.data

      // 隐藏loading
      if (config.showLoading) {
        this.hideLoading()
      }

      // 构造响应对象
      const response = {
        data: {
          code: 200,
          message: 'success',
          data: mockData
        },
        statusCode: 200,
        header: {
          'content-type': 'application/json'
        },
        config
      }

      // 处理响应拦截器
      return await this.processResponseInterceptors(response)
      
    } catch (error) {
      // 隐藏loading
      if (config.showLoading) {
        this.hideLoading()
      }

      // 处理Mock错误
      let errorData
      try {
        errorData = JSON.parse(error.message)
      } catch {
        errorData = {
          code: 500,
          message: error.message || 'Mock请求失败'
        }
      }

      const mockError = {
        message: errorData.message,
        code: errorData.code,
        response: {
          data: errorData,
          statusCode: errorData.code,
          header: {
            'content-type': 'application/json'
          }
        },
        config
      }

      if (config.showError) {
        this.showError(mockError.message)
      }

      throw mockError
    }
  }

  /**
   * 核心请求方法
   * @param {Object} options 请求选项
   * @returns {Promise} 请求Promise
   */
  async request(options) {
    // 合并配置
    const config = {
      ...this.config,
      ...options,
      header: {
        ...this.config.header,
        ...options.header
      }
    }

    // 处理URL
    if (config.url && !config.url.startsWith('http')) {
      config.url = config.baseURL + config.url
    }

    try {
      // 处理请求拦截器
      const processedConfig = await this.processRequestInterceptors(config)
      
      // 根据数据源类型处理请求
      if (processedConfig.dataSource === 'sqlite') {
        return await this.handleSqliteRequest(processedConfig)
      } else if (processedConfig.useMock || processedConfig.dataSource === 'mock') {
        return await this.handleMockRequest(processedConfig)
      }
      
      // 显示loading
      if (processedConfig.showLoading) {
        this.showLoading(processedConfig.loadingText)
      }

      // 发起请求
      const response = await new Promise((resolve, reject) => {
        uni.request({
          ...processedConfig,
          success: (res) => {
            resolve({
              data: res.data,
              statusCode: res.statusCode,
              header: res.header,
              config: processedConfig
            })
          },
          fail: (err) => {
            reject({
              message: err.errMsg || '网络请求失败',
              code: STATUS_CODE.NETWORK_ERROR,
              config: processedConfig
            })
          }
        })
      })

      // 隐藏loading
      if (processedConfig.showLoading) {
        this.hideLoading()
      }

      // 检查HTTP状态码
      if (response.statusCode !== STATUS_CODE.SUCCESS) {
        const error = {
          message: this.getErrorMessage(response.statusCode),
          code: response.statusCode,
          response,
          config: processedConfig
        }
        
        if (processedConfig.showError) {
          this.showError(error.message)
        }
        
        throw error
      }

      // 处理响应拦截器
      const processedResponse = await this.processResponseInterceptors(response)
      
      return processedResponse
      
    } catch (error) {
      // 隐藏loading
      if (config.showLoading) {
        this.hideLoading()
      }

      // 处理错误
      if (!error.code) {
        error.code = STATUS_CODE.NETWORK_ERROR
        error.message = this.getErrorMessage('default')
      }

      if (config.showError && !error.handled) {
        this.showError(error.message)
      }

      throw error
    }
  }

  /**
   * GET请求
   * @param {String} url 请求URL
   * @param {Object} params 请求参数
   * @param {Object} options 其他选项
   * @returns {Promise} 请求Promise
   */
  get(url, params = {}, options = {}) {
    return this.request({
      url,
      method: 'GET',
      data: params,
      ...options
    })
  }

  /**
   * POST请求
   * @param {String} url 请求URL
   * @param {Object} data 请求数据
   * @param {Object} options 其他选项
   * @returns {Promise} 请求Promise
   */
  post(url, data = {}, options = {}) {
    return this.request({
      url,
      method: 'POST',
      data,
      ...options
    })
  }

  /**
   * PUT请求
   * @param {String} url 请求URL
   * @param {Object} data 请求数据
   * @param {Object} options 其他选项
   * @returns {Promise} 请求Promise
   */
  put(url, data = {}, options = {}) {
    return this.request({
      url,
      method: 'PUT',
      data,
      ...options
    })
  }

  /**
   * DELETE请求
   * @param {String} url 请求URL
   * @param {Object} params 请求参数
   * @param {Object} options 其他选项
   * @returns {Promise} 请求Promise
   */
  delete(url, params = {}, options = {}) {
    return this.request({
      url,
      method: 'DELETE',
      data: params,
      ...options
    })
  }

  /**
   * 上传文件
   * @param {String} url 上传URL
   * @param {String} filePath 文件路径
   * @param {Object} formData 表单数据
   * @param {Object} options 其他选项
   * @returns {Promise} 上传Promise
   */
  upload(url, filePath, formData = {}, options = {}) {
    const config = {
      ...this.config,
      ...options
    }

    if (!url.startsWith('http')) {
      url = config.baseURL + url
    }

    return new Promise((resolve, reject) => {
      if (config.showLoading) {
        this.showLoading('上传中...')
      }

      uni.uploadFile({
        url,
        filePath,
        name: 'file',
        formData,
        header: config.header,
        success: (res) => {
          if (config.showLoading) {
            this.hideLoading()
          }
          
          try {
            const data = JSON.parse(res.data)
            resolve({ data, statusCode: res.statusCode })
          } catch (e) {
            resolve({ data: res.data, statusCode: res.statusCode })
          }
        },
        fail: (err) => {
          if (config.showLoading) {
            this.hideLoading()
          }
          
          const error = {
            message: err.errMsg || '上传失败',
            code: STATUS_CODE.NETWORK_ERROR
          }
          
          if (config.showError) {
            this.showError(error.message)
          }
          
          reject(error)
        }
      })
    })
  }
}

// 创建默认实例
const request = new RequestManager()

// 添加默认请求拦截器 - 添加token
request.addRequestInterceptor(
  (config) => {
    // 从本地存储获取token
    const token = uni.getStorageSync('token')
    if (token) {
      config.header.Authorization = `Bearer ${token}`
    }
    
    // 添加时间戳防止缓存
    if (config.method === 'GET') {
      const timestamp = Date.now()
      const separator = config.url.includes('?') ? '&' : '?'
      config.url += `${separator}_t=${timestamp}`
    }
    
    return config
  },
  (error) => {
    return Promise.reject(error)
  }
)

// 添加默认响应拦截器 - 处理业务逻辑
request.addResponseInterceptor(
  (response) => {
    const { data } = response
    
    // 假设后端返回格式为 { code: 0, data: {}, message: '' }
    if (data && typeof data === 'object') {
      if (data.code === 0 || data.code == 200) {
        // 成功，返回数据部分
        const ret = { ...response, data: data }
        return ret
      } else if (data.code === 401) {
        // token过期，清除本地token并跳转登录
        uni.removeStorageSync('token')
        uni.removeStorageSync('userInfo')
        uni.reLaunch({
          url: '/pages/login/index'
        })
        
        const error = {
          message: data.message || '登录已过期',
          code: data.code,
          handled: true
        }
        throw error
      } else {
        // 业务错误
        const error = {
          message: data.message || '请求失败',
          code: data.code,
          response
        }
        throw error
      }
    }
    
    return response
  },
  (error) => {
    return Promise.reject(error)
  }
)

export default request
export { RequestManager, STATUS_CODE, ERROR_MESSAGES }